// Copyright (c) 2022 by Duguang.IO Inc. All Rights Reserved.
// Author: Ethan Liu
// Date: 2022-06-26 21:22:10

package engine

import (
	"bufio"
	"context"
	"io"
)

// cancellableCopy method copies from source to destination honoring the context.
// If context.Cancel is called, it will return immediately with context cancelled error.
func cancellableCopy(ctx context.Context, dst io.Writer, src io.ReadCloser) error {
	ch := make(chan error, 1)
	go func() {
		defer close(ch)
		err := copy(dst, src)
		ch <- err
	}()

	select {
	case <-ctx.Done():
		src.Close()
		return ctx.Err()
	case err := <-ch:
		return err
	}
}

// Copy copies from src to dst and removes until either EOF
// is reached on src or an error occurs.
func copy(dst io.Writer, src io.ReadCloser) error {
	r := bufio.NewReader(src)
	for {
		bytes, err := r.ReadBytes('\n')
		if _, err := dst.Write(bytes); err != nil {
			return err
		}
		if err != nil {
			if err != io.EOF {
				return err
			}
			return nil
		}
	}
}
